package com.example.mr5.mygame.gameCatchCat;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;

import com.example.mr5.mygame.R;

import java.util.HashMap;
import java.util.Vector;

/**
 * Created by Mr.5
 * Date：2016/5/8.
 * Time：14:18
 */
public class GameView extends SurfaceView implements OnTouchListener {
    private int touchCount;
    private int topScore;
    private static int DOT_WIDTH = 40;        //圆点宽度
    private static final int ROW = 10;        //10行
    private static final int COL = 10;        //10列
    private static final int BLOCKS = 10;        //默认设置的路障数量为10
    private Dot matrix[][];                    //点的二维数组
    private Dot cat;                        //神经猫，本质上也是个点
//	private boolean justInit = true;

    public GameView(Context context) {
        super(context);
        getHolder().addCallback(callback);
        //初始化
        initGame();
        //设置触摸监听
        setOnTouchListener(this);    //因为实现了OnTouchListener,所以可以直接用this作为参数设置监听
    }

    /**
     * 初始化点的坐标与状态
     */
    private void initGame() {
        touchCount = 0;
        matrix = new Dot[ROW][COL];
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COL; j++) {
                matrix[i][j] = new Dot(j, i);
//				matrix[i][j].setStatus(Dot.STATUS_ON);
            }
        }
        cat = getDot(4, 5);
        cat.setStatus(Dot.STATUS_CAT);
        //随机关闭一些点
        for (int i = 0; i < BLOCKS; ) {
            int x = (int) (Math.random() * COL);    //X对应列
            int y = (int) (Math.random() * ROW);    //Y对应行
            if (matrix[x][y].getStatus() == Dot.STATUS_ON) {
                matrix[x][y].setStatus(Dot.STATUS_OFF);
                i++;
//				Log.e("Cat", "BLOCKS: "+x+" , "+y);
            }
        }
    }

    /**
     * 绘制界面
     */
    private void reDraw() {
        Canvas canvas = getHolder().lockCanvas();
        canvas.drawColor(Color.LTGRAY);        //背景为浅灰色
        Paint paint = new Paint();
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);    //设置抗锯齿
        for (int i = 0; i < ROW; i++) {
            int offset = 0;
            if (i % 2 == 1) {    //从0开始，偶数行，偏移半个DOT_WIDTH
                offset = DOT_WIDTH / 2;
            }
            for (int j = 0; j < COL; j++) {
                Dot one = getDot(j, i);

                switch (one.getStatus()) {
                    case Dot.STATUS_OFF:            //关闭的点为橙色
                        paint.setColor(0xFFFFAA00);
                        canvas.drawOval(new RectF(one.getX() * DOT_WIDTH + offset, one.getY() * DOT_WIDTH,
                                (one.getX() + 1) * DOT_WIDTH + offset, (one.getY() + 1) * DOT_WIDTH), paint);
                        break;
                    case Dot.STATUS_ON:                //开启的点为白色
                        paint.setColor(0xFFEEEEEE);
                        canvas.drawOval(new RectF(one.getX() * DOT_WIDTH + offset, one.getY() * DOT_WIDTH,
                                (one.getX() + 1) * DOT_WIDTH + offset, (one.getY() + 1) * DOT_WIDTH), paint);
                        break;
                    case Dot.STATUS_CAT:            //猫所在的点为红色
                        paint.setColor(0xFFFF0000);
                        RectF rectF = new RectF(one.getX() * DOT_WIDTH + offset, one.getY() * DOT_WIDTH,
                                (one.getX() + 1) * DOT_WIDTH + offset, (one.getY() + 1) * DOT_WIDTH);
                        Bitmap bitmap = BitmapFactory.decodeResource(this.getContext().getResources(), R.drawable.cat);
                        canvas.drawBitmap(bitmap, null, rectF, null);
                        break;

                    default:
                        break;
                }
                //绘制圆点
//				canvas.drawOval(new RectF(one.getX() * DOT_WIDTH + offset, one.getY() * DOT_WIDTH,
//						(one.getX() + 1) * DOT_WIDTH + offset, (one.getY() + 1) * DOT_WIDTH), paint);
//				RectF rectF = new RectF(one.getX() * DOT_WIDTH + offset, one.getY() * DOT_WIDTH,
//						(one.getX() + 1) * DOT_WIDTH + offset, (one.getY() + 1) * DOT_WIDTH);
//				Bitmap  bitmap = BitmapFactory.decodeResource(this.getContext().getResources(), R.drawable.ic_launcher);
//				canvas.drawBitmap(bitmap,null,rectF,null);
            }
        }
        Paint paint2 = new Paint();
        paint2.setColor(Color.RED);
        paint2.setTextSize(20);
        paint2.setTypeface(Typeface.MONOSPACE);
        canvas.drawText("别让狡猾的【红色圆点】接近墙边！", DOT_WIDTH / 2, (ROW + 2) * DOT_WIDTH, paint2);
        canvas.drawText("点击灰色区域重新开始", DOT_WIDTH * 2, (ROW + 4) * DOT_WIDTH, paint2);
        getHolder().unlockCanvasAndPost(canvas);    //解除锁定，绘制界面
    }


    /**
     * SurfaceHolder.Callback
     * 绘制内容
     */
    Callback callback = new Callback() {
        @Override
        public void surfaceDestroyed(SurfaceHolder arg0) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder arg0) {
            reDraw();
        }

        @Override
        public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
            DOT_WIDTH = arg2 / (COL + 1);
            reDraw();
        }
    };

    /**
     * 触摸事件的响应
     */
    @Override
    public boolean onTouch(View arg0, MotionEvent e) {
        if (e.getAction() == MotionEvent.ACTION_UP) {
            touchCount++;

            int x, y;
            y = (int) (e.getY() / DOT_WIDTH);
            if (y % 2 == 0)
                x = (int) (e.getX() / DOT_WIDTH);
            else
                x = (int) ((e.getX() - DOT_WIDTH / 2) / DOT_WIDTH);
            if (x + 1 <= COL && y + 1 <= ROW) {    //点击圆点区域以内的内容
                if (getDot(x, y).getStatus() == Dot.STATUS_ON) {
                    getDot(x, y).setStatus(Dot.STATUS_OFF);
                    move();
                }
                reDraw();
            } else {                            //点击圆点以外区域
                initGame();
                reDraw();
//				Dot next = getNighbour(cat, k);
//				if(next != null){
//					next.setStatus(Dot.STATUS_CAT);
//					k++;
//					reDraw();
//				}
//				Log.e("Touch Out Side:", x+" , "+y);
//				for (int i = 1; i < 7; i++) {
//					Log.e("getDistance:", "方向"+i+" getDistance(): "+getDistance(cat, i));
//				}

            }

        }
        return true;
    }

    /**
     * 转换一下坐标，不然有时候转不过来
     *
     * @param x
     * @param y
     * @return Dot
     */
    public Dot getDot(int x, int y) {
        return matrix[y][x];
    }


    /**
     * 判断一个点是否到了边界
     *
     * @param d 要判断的点
     * @return
     */
    private boolean isAtEdge(Dot d) {
        if (d.getX() * d.getY() == 0 || (d.getX() + 1) == COL ||
                (d.getY() + 1) == ROW)
            return true;
        return false;
    }

    /**
     * 获取一个点某方向上的邻点
     *
     * @param d   要判断的点
     * @param dir 方向，【1，6】，从正左边
     * @return
     */
    private Dot getNighbour(Dot one, int dir) {
//		Log.e("getNighbour", "one.getX():"+one.getX()+" , "+"one.getY()"+one.getY());
        switch (dir) {
            case 1:
                return getDot(one.getX() - 1, one.getY());
            case 2:
                if (one.getY() % 2 == 0) {    //奇数行，没有偏移de
                    return getDot(one.getX() - 1, one.getY() - 1);
                } else {
                    return getDot(one.getX(), one.getY() - 1);
                }
            case 3:
                if (one.getY() % 2 == 0) {    //奇数行，没有偏移de
                    return getDot(one.getX(), one.getY() - 1);
                } else {
                    return getDot(one.getX() + 1, one.getY() - 1);
                }
            case 4:
                return getDot(one.getX() + 1, one.getY());
            case 5:
                if (one.getY() % 2 == 0) {    //奇数行，没有偏移de
                    return getDot(one.getX(), one.getY() + 1);
                } else {
                    return getDot(one.getX() + 1, one.getY() + 1);
                }
            case 6:
                if (one.getY() % 2 == 0) {    //奇数行，没有偏移de
                    return getDot(one.getX() - 1, one.getY() + 1);
                } else {
                    return getDot(one.getX(), one.getY() + 1);
                }


            default:
                break;
        }
        return null;
    }

    /**
     * 计算最多可走的路径
     *
     * @param one 当前节点
     * @param dir 方向
     * @return 距离，<=0表示遇到路障 ， >0表示可以走到边界
     */
    private int getDistance(Dot one, int dir) {
        int distance = 0;
        if (isAtEdge(one)) {
            return 1;
        }
        Dot original = one;        //当前选择点
        Dot next;            //下一个点
        while (true) {
            next = getNighbour(original, dir);
//			Log.e("getDistance", dir+" next:"+next.getX()+" , "+next.getY());
            if (next.getStatus() == Dot.STATUS_OFF) {
                return distance * -1;
            }
            if (isAtEdge(next)) {
                distance++;
                return distance;
            }
            distance++;
            original = next;
        }
    }

    /**
     * 移动到新点
     *
     * @param newPlace 新的点
     */
    private void catMoveTo(Dot newPlace) {
        Log.e("catMoveTo", "moveto  :  " + newPlace.getX() + " , " + newPlace.getY());
//		Log.e("cat:", "cat(x,y) :"+ cat.getX()+" , "+ cat.getY());
        newPlace.setStatus(Dot.STATUS_CAT);
        cat.setStatus(Dot.STATUS_ON);
        cat = newPlace;                        //猫移动到新位置，并且修改颜色
//		Dot old = getDot(cat.getX(),cat.getY());
//		old.setStatus(Dot.STATUS_ON);
//		cat.setXY(newPlace.getX(), newPlace.getY());	
//		cat.setStatus(Dot.STATUS_CAT);
        if (isAtEdge(cat)) {            //你居然被神经病猫跑到了墙边，认输吧你个蠢蛋
            lose();
            return;
        }
    }

    /**
     * 猫移动前的判断
     */
    private void move() {
        if (isAtEdge(cat)) {            //你居然被神经病猫跑到了墙边，认输吧你个蠢蛋
            Toast.makeText(getContext(), "别点了，你已经被电脑打败了", 0).show();
            return;
        }
        Vector<Dot> available = new Vector<Dot>();        //可用的容器
        Vector<Dot> positive = new Vector<Dot>();        //能直接到边界的容器
        HashMap<Dot, Integer> al = new HashMap<Dot, Integer>();    //记录方向
        for (int i = 1; i < 7; i++) {
            Dot n = getNighbour(cat, i);
            al.put(n, i);            //记录[可直达点, 对应的方向](key,value)
            if (n.getStatus() == Dot.STATUS_ON) {        //加入可用容器中
                available.add(n);
                if (getDistance(n, i) > 0)        //可以直接到达边界
                    positive.add(n);            //加入到可直达容器中
            }
        }
//		Log.e("move", "available : "+ available.size());
        if (available.size() <= 0) {            //没有可移动的点，神经猫被逼入绝境，你赢了！
            win();
            return;
        } else if (available.size() == 1) {
            catMoveTo(available.get(0));
        } else {        //狡猾的算法---最短路径
            Dot best = null;
            if (positive.size() != 0) {        //有可以直达的，就选一条最短的
                int min = 999;
                for (int i = 0; i < positive.size(); i++) {
                    int distance = getDistance(positive.get(i), al.get(positive.get(i)));
                    if (distance < min) {
                        min = distance;
                        best = positive.get(i);
                    }
                }

            } else {    //所有方向都有路障，就选一个，可能最短的
                int max = 0;
                for (int i = 0; i < available.size(); i++) {
                    int k = getDistance(available.get(i), al.get(available.get(i)));
                    if (k < max) {
                        max = k;
                        best = available.get(i);
                    }
                }
            }
            if (best != null) {
                Log.e("move", "最佳选择： " + best.getX() + " , " + best.getY());
                System.out.println(best.getX() + " , " + best.getY());
                catMoveTo(best);
            } else {
                Log.e("move", "win!");
//				win();
            }
        }

    }

    private void lose() {
        Toast.makeText(getContext(), "居然让他跑了，你个笨蛋!", 0).show();
    }

    private void win() {
        Toast.makeText(getContext(), "你用了【 " + touchCount + " 】步围住了红点！", 0).show();
    }
}
